#ifndef __PROTOCOL_HPP__
#define __PROTOCOL_HPP__

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>

class Request
{
public:
    Request()
    {
        _x = _y = _oper = 0;
    }

    bool Serialize(std::string *out)
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        Json::StyledWriter writer;
        *out = writer.write(root);
        if(out->empty())
        {
            return false;
        }
        return true;
    }

    bool Deserialize(std::string& in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ret = reader.parse(in, root);
        if(!ret)
            return false;
        
        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _oper = root["oper"].asInt();
        return true;
    }

    int X()
    {
        return _x;
    }

    int Y()
    {
        return _y;
    }

    char Oper()
    {
        return _oper;
    }

    ~Request(){}

//private:
public:
    int _x;
    int _y;
    char _oper;
};

class Response
{
public:
    Response()
        :_result(0)
        ,_code(0)
    {}

    bool Serialize(std::string* out)
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::StyledWriter writer;
        *out = writer.write(root);
        if(out->empty())
        {
            return false;
        }
        return true;
    }

    bool Deserialize(std::string& in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ret = reader.parse(in, root);
        if(!ret)
        {
            return false;
        }

        _result = root["result"].asInt();
        _code = root["root"].asInt();
        return true;
    }

    void SetResult(int r)
    {
        _result = r;
    }
    void SetCode(int c)
    {
        _code = c;
    }
    void Print()
    {
        std::cout << _result << "[" << _code << "]" << std::endl;
    }

    ~Response(){}
private:
    int _result;
    int _code;//可不可信 可信为0，不可信为1
};

static const std::string sep = "\r\n";

class Protocol
{
public:
    static std::string Package(const std::string& jsonstr)
    {
        //jsonstr->len\r\njsonstr\r\n
        if(jsonstr.empty())
        {
            return std::string();
        }
        std::string len_str = std::to_string(jsonstr.size());
        return len_str + sep + jsonstr + sep;
    }


    static bool DigitSafeCheck(const std::string str)//判断长度字符串是否合法
    {
        for(int i = 0 ;i < str.size(); i++)
        {
            if(!(str[i] >= '0' && str[i] <= '9'))
                return false;
        }
        return true;
    }

    // len\r\njsonstr\r\n
    // len\r\njsonstr\r\nlen\r\njsonstr\r\n
    // len\r\njsonstr\r\nlen\r
    // len\r\n
    // len\r\njs
    // len\r
    // len
    //每次拆完一个完整的包就把这一部分去掉
    static int UnPackage(std::string& origin_str, std::string* package)
    {
        if(!package)
        {
            return 0;
        }
        auto pos = origin_str.find(sep);
        if(pos == std::string::npos)
        {
            return 0;
        }

        std::string len_str = origin_str.substr(0, pos);
        if(!DigitSafeCheck(len_str))
            return -1;
        int digit_len = std::stoi(len_str);//报文的长度（jsonstr）
        //这是我们可以得知一个完整报文的长度（报头长度+报文长度）
        int target_len = len_str.size() + digit_len + sep.size() * 2;
        if(origin_str.size() < target_len)
            return 0;
        *package = origin_str.substr(pos + sep.size(), digit_len);
        origin_str.erase(0, target_len);
        return digit_len;
    }
};

#endif